package com.lyrcsoft.webflux_01.reactor;

import reactor.core.publisher.Flux;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class ReactorDemo2 {
    // 模拟一些产品
    private static Product[] products = new Product[]{
            new Product(1, new BigDecimal("9.92"), 100, "E"),
            new Product(2, new BigDecimal("19.92"), 200, "E"),
            new Product(3, new BigDecimal("29.92"), 500, "E"),

            new Product(4, new BigDecimal("19.92"), 200, "C"),
            new Product(5, new BigDecimal("9.32"), 300, "C"),
            new Product(6, new BigDecimal("18.92"), 100, "C"),

            new Product(7, new BigDecimal("23.76"), 300, "M"),
            new Product(8, new BigDecimal("11.92"), 150, "M"),
            new Product(9, new BigDecimal("78.08"), 100, "M"),
    };

    // 获取价格最高的产品
    public List<Product> getHighestPriceProduct() {
        Map<String, Product> map = new HashMap<>();
        for (Product product : products) {
            String category = product.getCategory();
            Product p = map.get(category);
            if (p != null) {
                if (p.getPrice().compareTo(product.getPrice()) < 0) {
                    map.put(category, product);
                }
            } else {
                map.put(category, product);
            }
        }
        return map.values().stream().collect(Collectors.toList());
    }

    public Flux<Product> getHighestPriceProductReactor() {
        return Flux.just(Arrays.asList(products)).flatMap(list -> {
            Map<String, Product> map = new HashMap<>();
            for (Product product : list) {
                String category = product.getCategory();
                Product p = map.get(category);
                if (p != null) {
                    if (p.getPrice().compareTo(product.getPrice()) < 0) {
                        map.put(category, product);
                    }
                } else {
                    map.put(category, product);
                }
            }
            return Flux.fromIterable(map.values().stream().collect(Collectors.toList()));
        });
    }

    public Flux<Product> getHighestPriceProductReactor2() {
        // 更优雅的处理，先分组。分组之后排序，再取头
        return Flux.just(products).collectMultimap(Product::getCategory) // 分组，拿到的结果是groupsMap
                // 把分组后的groupsMap转成Flux
                .flatMapMany(groups -> Flux.fromIterable(groups.entrySet())) //为什么取entrySet？我们如果要遍历Map，遍历的是entrySet
                // 下一步，Flux Map传进来之后
                .flatMap(map ->
                        // 将map值转成Flux,然后排序，取第一个
                        Flux.fromIterable(map.getValue())
                                .sort(Comparator.comparing(Product::getPrice).reversed())
                                .next())
                ;
        // 流式编程，是一个链路，在执行过程中的时候，把处理结果给下一个处理，而不是把结果全部取出来，然后再处理
        // 原来的编程：将结果已经取出来，然后再遍历
    }

    public static void main(String[] args) {
        ReactorDemo2 reactorDemo2 = new ReactorDemo2();
        reactorDemo2.getHighestPriceProduct().forEach(System.out::println);
        reactorDemo2.getHighestPriceProductReactor().subscribe(System.out::println);
        reactorDemo2.getHighestPriceProductReactor2().subscribe(System.out::println);
    }


}
